/**
 * 编辑器
 */
class MyEditor {
    constructor() {
        /*编辑器*/
        this.editor = document.querySelector('#editor');
        /*工具栏*/
        this.toolbar = document.querySelector('.toolbar');
        /*初始事件*/
        this.init();
    }

    /*初始事件*/
    init(){
        /*工具栏的事件*/
        this.toolbarEvent();
        /*编辑框的事件*/
        this.editorEvent();
        /*初始化editor的内容状态*/
        this.updatePlaceholder();
    }


    /**
     * 工具栏的事件
     */
    toolbarEvent(){
        this.toolbar.addEventListener('click', (e) => {
            const button = e.target.closest('button');
            if (!button) return;

            const command = button.dataset.command;
            if (command) {
                /*获取被选中的文本*/
                this.execCommandStyle(command);
            }
        });
    }

    /**
     * 编辑框的事件
     */
    editorEvent(){
        /*监听输入事件*/
        this.editor.addEventListener('input', (e)=>{
            this.updatePlaceholder(e);
        });
        /*监听blur事件*/
        this.editor.addEventListener('blur', (e)=>{
            this.updatePlaceholder(e);
        });
        /*监听focus事件*/
        this.editor.addEventListener('focus', (e)=>{
            this.updatePlaceholder(e);
        });
    }


    /**
     * 更新编辑框状态
     */
    updatePlaceholder(){
        /*判断编辑框的内容是否为空*/
        const isEmpty = this.editor.textContent.trim() === '' &&  this.editor.children.length === 0;
        const hasOnlyEmptyTags =  this.editor.children.length === 1 &&
            ( this.editor.firstElementChild.tagName === 'P' ||  this.editor.firstElementChild.tagName === 'BR') &&
            this.editor.firstElementChild.textContent.trim() === '';
        if (isEmpty || hasOnlyEmptyTags) {
            this.editor.classList.remove('has-content');
        } else {
            this.editor.classList.add('has-content');
        }
    }

    /**
     * 切换选中文本的样式（加粗、斜体、下划线等）
     * 如果选区包含指定样式，则移除；否则，添加
     * @param command 要切换的 HTML 标签名（例如 'strong', 'em', 'u'）
     */
    execCommandStyle(command){
        let styleType ;
        const selection = window.getSelection();
        /*没有选区*/
        if (!selection.rangeCount) return;
        /*获取选区范围*/
        const range = selection.getRangeAt(0);
        /*被框选的纯文本*/
        const selectedText = range.toString();
        /*如果没有选中任何文本，且选区不是折叠的（即光标不在文本中），则不进行操作*/
        if (selectedText.length === 0 && !range.collapsed) {
            return;
        }

        switch (command){
            case 'bold':
                styleType = 'strong';
                break;
            case 'underline':
                styleType = 'u';
                break;
            case 'italic':
                styleType = 'em';
                break;
            case 'strikeThrough':
                styleType = 's';
                break;
        }

        /*判断被框选的部分是不是被对应样式包裹了*/
        const isStyled = this.isSelectionStyled(selection, styleType, this.editor);
        console.log(isStyled,'ooooooooooooooooooooo')
        /*如果框选部分已经有样式包裹*/
        if (isStyled){
            /* 移除样式 (unwrap)；尝试找到选区共同祖先中最近的样式标签进行解包*/
            let nodeToUnwrap = this.getClosestAncestor(range.commonAncestorContainer, styleType,this.editor);
            console.log(nodeToUnwrap,'isStyled===true')
            if (nodeToUnwrap && nodeToUnwrap !== this.editor) {
                // 如果找到的样式节点完全包含在选区内，或者选区完全包含它，则对其进行解包。
                // 注意：此处的解包是针对整个 `nodeToUnwrap` 元素，
                // 对于仅选中部分样式文本的情况，可能无法实现精确的“部分解包”，
                // 这需要更复杂的 DOM 节点分裂和重组逻辑。
                const parent = nodeToUnwrap.parentNode;
                while (nodeToUnwrap.firstChild) {
                    parent.insertBefore(nodeToUnwrap.firstChild, nodeToUnwrap);
                }
                parent.removeChild(nodeToUnwrap);
                // 恢复选区，确保用户体验连贯
                selection.removeAllRanges();
                selection.addRange(range);
                console.log('111111111111111111111111111');

            } else {
                // 如果无法找到一个可解包的完整样式节点（例如，选区只覆盖了样式节点的一部分），
                // 此时需要更复杂的逻辑来分裂节点并移除样式。
                // 在此示例中，我们简化处理：直接用纯文本替换选中的样式文本。
                // 这不是一个完美的“解包”，但能达到移除样式的效果。
                const textNode = document.createTextNode(selectedText);
                range.deleteContents();
                range.insertNode(textNode);
                // selection.removeAllRanges();
                const newRange = document.createRange();
                newRange.selectNode(textNode);
                selection.addRange(newRange);
                console.log('22222222222222222222222222');
            }


        }else {
            console.log(isStyled,'isStyled===false')
            /*添加对应的样式*/
            const newElement = document.createElement(styleType);
            try {
                // surroundContents 尝试将选区内容用新元素包裹。
                // 如果选区跨越了复杂的节点边界（例如，部分选中一个文本节点），
                // surroundContents 可能会抛出错误。
                range.surroundContents(newElement);
                // 重新选中新包裹的内容，以便用户可以继续操作
                const newRange = document.createRange();
                newRange.selectNodeContents(newElement);
                // selection.removeAllRanges();
                selection.addRange(newRange);
            }catch (e){
                // 如果 surroundContents 失败，手动创建新元素并插入选中的文本。
                // 这会替换掉选中的文本，并应用样式。
                const textNode = document.createTextNode(selectedText);
                newElement.appendChild(textNode);
                range.deleteContents();
                range.insertNode(newElement);
                // 重新选中新插入的内容
                const newRange = document.createRange();
                newRange.selectNodeContents(newElement);
                // selection.removeAllRanges();
                selection.addRange(newRange);
            }
            console.log(newElement,'ddddddddddddddddddddddddddd')

        }

    }

    /**
     * 判断当前选区是否包含指定样式的元素。
     * @param {Selection} selection - 当前的 Selection 对象。
     * @param {string} tagName - 要检查的标签名（例如 'strong', 'em'）。
     * @param {HTMLElement} editor - 编辑器根节点。
     * @returns {boolean} 如果选区包含指定样式则返回 true，否则返回 false。
     */
    isSelectionStyled(selection, tagName, editor) {
        if (!selection || !selection.rangeCount) return false;

        const range = selection.getRangeAt(0);

        // 如果选区是折叠的（光标），检查光标所在位置的父节点是否有样式
        if (range.collapsed) {
            return !!this.getClosestAncestor(selection.anchorNode, tagName, editor);
        }

        // 对于非折叠选区，检查选区内的内容是否有样式
        // 1. 检查共同祖先节点是否是目标样式标签或其子孙
        let commonAncestor = range.commonAncestorContainer;
        if (this.getClosestAncestor(commonAncestor, tagName, editor)) {
            return true;
        }

        // 2. 克隆选区内容并查询，看是否有目标样式标签
        // 这是一个启发式方法，对于复杂的嵌套和部分选择可能不完全准确，
        // 但对于常见情况有效。
        const fragment = range.cloneContents();
        return fragment.querySelectorAll(tagName).length > 0;

    }

    /**
     * 获取给定节点最近的、匹配指定标签名的祖先元素。
     * 搜索范围限制在 editorNode 内部。
     * @param {Node} node - 当前节点。
     * @param {string} tagName - 要查找的标签名（例如 'strong', 'em'）。
     * @param {HTMLElement} editorNode - 编辑器根节点，搜索不会超出此节点。
     * @returns {HTMLElement | null} 匹配的祖先元素，如果没有找到则返回 null。
     */
    getClosestAncestor(node, tagName, editorNode) {
        let current = node;
        while (current && current !== editorNode) {
            console.log(current.nodeType,'fffffffffffffffffffffff')
            console.log(Node.ELEMENT_NODE,'editorNode')
            console.log(current.tagName,'current.tagName')
            console.log(current.parentNode,'current.parentNode')
            if (current.nodeType === Node.ELEMENT_NODE && current.tagName.toLowerCase() === tagName) {
                return current;
            }
            current = current.parentNode;
        }
        return null;
    }

}

// 初始化编辑器
window.onload = function (){
    new MyEditor();
}
